package com.liuc.practice.server;

import com.liuc.practice.server.pojo.Request;
import com.liuc.practice.server.pojo.Response;
import com.liuc.practice.server.servlet.HttpServlet;
import com.liuc.practice.server.servlet.Servlet;
import com.liuc.practice.server.thread.RequestProcessor;
import com.liuc.practice.server.util.HttpProtocolResponseUtil;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.Node;
import org.dom4j.io.SAXReader;

import java.io.*;
import java.net.*;
import java.util.*;
import java.util.concurrent.*;

/**
 * @Author Liu Chang
 * @Date 2021/7/21 9:28 下午
 *
 * minicat 主类
 */
public class Bootstrap {

    private void start() throws Exception {


        /**
         * V1.0 浏览器请求 http://localhost:8080 返回页面："Hello minicat"
         */
        /* while (true) {
            Socket accept = serverSocket.accept();

            OutputStream outputStream = accept.getOutputStream();
            String content = "Hello minicat";
            String success = HttpProtocolResponseUtil.successHeader(content.getBytes().length) + content;
            outputStream.write(success.getBytes());

        }*/
//        serverSocket.close();

        /**
         * V2.0 封装 Request 对象和 Response 对象，返回 html 静态资源文件
         */
        /*while (true) {
            Socket socket = serverSocket.accept();

            // 获取请求信息
            InputStream inputStream = socket.getInputStream();

            Request request = new Request(inputStream);
            Response response = new Response(socket.getOutputStream());

            response.outputHtml(request.getUrl());
            serverSocket.close();
        }*/

        /**
         * V3.0 可以请求动态资源
         * 1. 加载解析 web.xml，初始化 Servlet
         * 2. 可以接受静态请求以及动态请求
         */

        // 报错：Socket is not bound yet，未绑定端口号
        // port 从 server.xml 中读取，所以先解析 service.xml，再进行 socket 连接
/*        ServerSocket serverSocket = new ServerSocket(port);
        System.out.println("minicat start on port:" + port);*/
        /*while (true) {
            Socket socket = serverSocket.accept();
            InputStream inputStream = socket.getInputStream();

            Request request = new Request(inputStream);
            Response response = new Response(socket.getOutputStream());

            // 根据 map 中是否有 url 区别是否为动态请求
            if (servletMap.get(request.getUrl()) == null) {
                response.outputHtml(request.getUrl());
            } else {
                HttpServlet httpServlet = servletMap.get(request.getUrl());
                httpServlet.service(request, response);
            }
            // serverSocket.close();
        }*/

        /**
         * 多线程改造(未使用线程池)
         */
        /*while (true) {
         Socket socket = serverSocket.accept();
            RequestProcessor requestProcessor = new RequestProcessor(socket, servletMap);
            requestProcessor.start();
        }*/

        Mapper mapper = new Mapper();
        mapper.parseServerXML();
        /**
         * 多线程改造（使用线程池）
         */
        // 自定义线程池
        ServerSocket serverSocket = new ServerSocket(Integer.parseInt(mapper.getPort()));
        System.out.println("minicat start on port:" + mapper.getPort());

        int corePoolSize = 10;
        int maximumPoolSize = 50;
        long keepAliveTime = 100L;
        TimeUnit unit = TimeUnit.SECONDS;
        BlockingQueue<Runnable> workQueue = new ArrayBlockingQueue<>(50);
        ThreadFactory threadFactory = Executors.defaultThreadFactory();
        RejectedExecutionHandler handler = new ThreadPoolExecutor.AbortPolicy();

        ThreadPoolExecutor executor = new ThreadPoolExecutor(
                corePoolSize,
                maximumPoolSize,
                keepAliveTime,
                unit,
                workQueue,
                threadFactory,
                handler);
        while (true) {
            Socket socket = serverSocket.accept();
            RequestProcessor requestProcessor = new RequestProcessor(socket, mapper.getContext());
            executor.execute(requestProcessor);

        }
    }

    public static void main(String[] args) {
        Bootstrap bootstrap = new Bootstrap();
        try {
            bootstrap.start();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (DocumentException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}
